/**
 * 
 */
package io.zhijian.app.config;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;

import io.zhijian.app.authorization.CustomRolesAuthorizationFilter;
import io.zhijian.app.authorization.RetryLimitHashedCredentialsMatcher;
import io.zhijian.app.authorization.UserAuthRealm;

/**
 * <p>Title:ShiroConfig </p>
 * <p>Description: </p>
 * <p>Company:ipebg </p> 
 * @author H2013788
 * @date 2019年8月7日
 */
@Configuration
public class ShiroConfig {
	
	@Bean(name = "ehcache")  
	public EhCacheManagerFactoryBean ehCacheFactory(){  
	    EhCacheManagerFactoryBean ehCacheFactory = new EhCacheManagerFactoryBean();  
	    ehCacheFactory.setConfigLocation(new ClassPathResource("ehcache.xml"));  
	    ehCacheFactory.setShared(true);  
	    return ehCacheFactory;  
	} 
	
	@Bean
	public EhCacheManager shiroEhcacheManager() {
		EhCacheManager ehcacheManager = new EhCacheManager();
		ehcacheManager.setCacheManager(ehCacheFactory().getObject());
		return ehcacheManager;
	}
	
	@Bean
	public EhCacheManager cacheManager() {
		EhCacheManager ehcacheManager = new EhCacheManager();
		ehcacheManager.setCacheManager(ehCacheFactory().getObject());
		return ehcacheManager;
	}
	
	@DependsOn({"roleOrFilter"})
	@Bean(name="shiroFilterFactoryBean")
	public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);		//设置安全管理器
		shiroFilterFactoryBean.setLoginUrl("/login");// 	如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
	    shiroFilterFactoryBean.setSuccessUrl("/index"); //  登录成功后要跳转的链接
	    shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");//未授权界面;
	    Map<String, Filter> filterMap = shiroFilterFactoryBean.getFilters();
	    filterMap.put("roleOrFilter", roleOrFilter());
	    shiroFilterFactoryBean.setFilters(filterMap);
	    Map<String, String> filterChainDefinitionMap = new HashMap<String, String>();
	    filterChainDefinitionMap.put("/index.html","anon");
	    filterChainDefinitionMap.put("/login","anon");
	    filterChainDefinitionMap.put("/api/**","anon");
	    filterChainDefinitionMap.put("/verifyImg","anon");
	    filterChainDefinitionMap.put("/index.html","anon");
	    filterChainDefinitionMap.put("/front/**","anon");
	    filterChainDefinitionMap.put("/timeout","anon");
	    filterChainDefinitionMap.put("/style/**","anon");
	    filterChainDefinitionMap.put("/uploads/**","anon");
	    filterChainDefinitionMap.put("/postApi/**","anon");
	    filterChainDefinitionMap.put("/search/**","anon");
	    filterChainDefinitionMap.put("/template/**","logout");//配置退出 过滤器,其中的具体的退出代码Shiro已经实现
	    filterChainDefinitionMap.put("/**","authc");//过滤链定义，从上向下顺序执行，一般将/**放在最为下边
	    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
	    return shiroFilterFactoryBean ;
			
	}
	
	@Bean
	public CustomRolesAuthorizationFilter roleOrFilter() {
		return new CustomRolesAuthorizationFilter();
    }

	//权限管理，配置主要是Realm的管理认证
	@Bean(name="securityManager")
	public DefaultWebSecurityManager securityManager(){
		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
	    securityManager.setRealm(userRealm());        //设置realm.
        // 自定义缓存实现 使用redis
        // securityManager.setCacheManager(redisCacheManager());
        // 自定义session管理 使用redis
        // securityManager.setSessionManager(sessionManager());
	    securityManager.setCacheManager(shiroEhcacheManager());
	    return securityManager;
	 }
	
	//将自己的验证方式加入容器
	@Bean(name="userAuthRealm")
	public UserAuthRealm userRealm(){
		UserAuthRealm userRealm = new UserAuthRealm();
		userRealm.setCredentialsMatcher(credentialsMatcher());
	    return userRealm;
	}
	
	
	@DependsOn({ "transactionManager"})
	@Order(Ordered.LOWEST_PRECEDENCE)
	@Bean
	public RetryLimitHashedCredentialsMatcher credentialsMatcher() {
		RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(
				shiroEhcacheManager());
		credentialsMatcher.setHashAlgorithmName("md5");
		credentialsMatcher.setHashIterations(2);
		credentialsMatcher.setStoredCredentialsHexEncoded(true);
		return credentialsMatcher;
	}
	

	
	/**
	 * 以下三個方法用於開啟註解支持
	 * @return
	 * @author H2013788
	 * @date 2019年8月9日
	 */
	@Bean
	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@Bean
	@DependsOn({ "lifecycleBeanPostProcessor" })
	public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
		advisorAutoProxyCreator.setProxyTargetClass(true);
		return advisorAutoProxyCreator;
	}
	
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
		return authorizationAttributeSourceAdvisor;
	}
	
}

